from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.db.postgres import get_session
from app.models import DictionaryItem, DictionaryType
from app.schemas.dictionary import (
    DictionaryItemCreate,
    DictionaryItemRead,
    DictionaryItemUpdate,
    DictionaryTypeCreate,
    DictionaryTypeUpdate,
    DictionaryTypeRead,
)


router = APIRouter(prefix="/dictionaries", tags=["dictionaries"])


@router.get("/items", response_model=list[DictionaryItemRead])
async def list_items(
    type_code: str = Query(...),
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    session: AsyncSession = Depends(get_session),
):
    stmt = select(DictionaryItem).where(DictionaryItem.type_code == type_code).order_by(DictionaryItem.order_index)
    result = await session.execute(stmt.offset((page - 1) * page_size).limit(page_size))
    return [DictionaryItemRead.model_validate(x) for x in result.scalars().all()]


@router.post("/items", response_model=DictionaryItemRead)
async def create_item(payload: DictionaryItemCreate, session: AsyncSession = Depends(get_session)):
    obj = DictionaryItem(**payload.model_dump())
    session.add(obj)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return DictionaryItemRead.model_validate(obj)


@router.put("/items/{item_id}", response_model=DictionaryItemRead)
async def update_item(item_id: str, payload: DictionaryItemUpdate, session: AsyncSession = Depends(get_session)):
    obj = await session.get(DictionaryItem, item_id)
    if not obj:
        raise HTTPException(status_code=404, detail="字典项不存在")
    for k, v in payload.model_dump(exclude_unset=True).items():
        setattr(obj, k, v)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return DictionaryItemRead.model_validate(obj)


@router.delete("/items/{item_id}")
async def delete_item(item_id: str, session: AsyncSession = Depends(get_session)):
    obj = await session.get(DictionaryItem, item_id)
    if not obj:
        raise HTTPException(status_code=404, detail="字典项不存在")
    await session.delete(obj)
    await session.commit()
    return {"ok": True}


# Types CRUD
@router.get("/types", response_model=list[DictionaryTypeRead])
async def list_types(session: AsyncSession = Depends(get_session)):
    result = await session.execute(select(DictionaryType).order_by(DictionaryType.code))
    return [DictionaryTypeRead.model_validate(x) for x in result.scalars().all()]


@router.post("/types", response_model=DictionaryTypeRead)
async def create_type(payload: DictionaryTypeCreate, session: AsyncSession = Depends(get_session)):
    obj = DictionaryType(**payload.model_dump())
    session.add(obj)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return DictionaryTypeRead.model_validate(obj)


@router.get("/types/{code}", response_model=DictionaryTypeRead)
async def get_type(code: str, session: AsyncSession = Depends(get_session)):
    obj = await session.get(DictionaryType, code)
    if not obj:
        raise HTTPException(status_code=404, detail="字典类型不存在")
    return DictionaryTypeRead.model_validate(obj)


@router.put("/types/{code}", response_model=DictionaryTypeRead)
async def update_type(code: str, payload: DictionaryTypeUpdate, session: AsyncSession = Depends(get_session)):
    obj = await session.get(DictionaryType, code)
    if not obj:
        raise HTTPException(status_code=404, detail="字典类型不存在")
    for k, v in payload.model_dump(exclude_unset=True).items():
        setattr(obj, k, v)
    await session.flush()
    await session.refresh(obj)
    await session.commit()
    return DictionaryTypeRead.model_validate(obj)


@router.delete("/types/{code}")
async def delete_type(code: str, session: AsyncSession = Depends(get_session)):
    obj = await session.get(DictionaryType, code)
    if not obj:
        raise HTTPException(status_code=404, detail="字典类型不存在")
    await session.delete(obj)
    await session.commit()
    return {"ok": True}
